﻿using adb;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using System.Linq;
using Z.EntityFramework.Plus;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using adb.excel;
using System.IO;
using Microsoft.Net.Http.Headers;
using System;
using PowerStation.AppCode;
using PowerStation.RequestModel;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using utils;

namespace PowerStation.Controllers
{
    /// <summary>
    /// 设备管理
    /// </summary>
    public class DeviceController : BaseApi<DeviceController>
    {
        /// <summary>
        /// 
        /// </summary>
        public IMqttModel mqtt { get; }
        private readonly RedisUtil _redisUtil;
        /// <summary>
        /// 设备管理
        /// </summary>
        /// <param name="content"></param>
        /// <param name="mqtt"></param>
        /// <param name="redisUtil"></param>
        public DeviceController(IHttpContextAccessor content, IMqttModel mqtt, RedisUtil redisUtil) : base(content)
        {
            this.mqtt = mqtt;
            this._redisUtil = redisUtil;
        }



        /// <summary>
        /// 列表
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<List<vPowerStationDevice>>> List(decimal powerStationId, [FromQuery] RequestMultipleSearchModel model)
        {
            await this.IsCheckPowerStation(powerStationId);
            IQueryable<vPowerStationDevice> q = this._db.vPowerStationDevice.Where(x => x.devicePowerStation_powerStationId_fk == powerStationId).OrderBy(x => x.dataOrderBy);
            foreach (var item in model.searchItem)
            {

                if (item.typeName == "设备名称")
                {
                    q = q.Where(x => x.deviceName.Contains(item.value));
                }
                else if (item.typeName == "设备类型")
                {
                    q = q.Where(x => x.Type == item.value);
                }
            }
            q = q.OrderByDescending(x => x.deviceId);
            var s = await model.setPageAsync(q);
            return ResultApi.ok<List<vPowerStationDevice>>(await s.Item2.ToListAsync(), s.Item1);
        }
        /// <summary>
        /// 获取电站内的所有硬件
        /// </summary>
        /// <param name="powerStationId">电站ID</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<List<tPowerStationDevice>>> ListAll(decimal powerStationId)
        {
            await this.IsCheckPowerStation(powerStationId);
            IQueryable<tPowerStationDevice> q = this._db.tPowerStationDevice.Where(x => x.devicePowerStation_powerStationId_fk == powerStationId);
            q = q.OrderByDescending(x => x.deviceId);
            return ResultApi.ok<List<tPowerStationDevice>>(await q.ToListAsync(), 0);
        }
        /// <summary>
        /// 删除设备
        /// </summary>
        /// <param name="deviceIds">设备ID</param>
        /// <returns></returns>
        [HttpDelete]
        public async Task<ResultApi<bool>> Delete(List<decimal> deviceIds)
        {

            using (var tran = await this._db.Database.BeginTransactionAsync())
            {
                List<tPowerStationDevice> lst = new List<tPowerStationDevice>();
                foreach (var deviceId in deviceIds)
                {
                    var m = await this._db.tPowerStationDevice.FirstOrDefaultAsync(x => x.deviceId == deviceId && x.dataState == 0);
                    lst.Add(m);
                    await IsCheckPowerStation(m.devicePowerStation_powerStationId_fk);
                    await this._db.tPowerStationDevice.Where(x => x.deviceId == deviceId).UpdateAsync(x => new tPowerStationDevice { dataState = 1 });
                    await this._db.SaveChangesAsync();
                }
                //if (lst.Count() == deviceIds.Count()) {
                //    foreach (var item in lst)
                //    {
                //        await this.mqtt.Disconnect(item.deviceSN);
                //    }

                tran.Commit();
                return ResultApi.okOrError<bool>(true, true);
                //}
                //tran.Rollback();
                //return ResultApi.error(false);
            }


        }


        /// <summary>
        /// 设备详情
        /// </summary>
        /// <param name="deviceId">设备详情</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<tPowerStationDevice>> Detial(decimal deviceId)
        {
            var m = await this._db.tPowerStationDevice.FirstOrDefaultAsync(x => x.deviceId == deviceId && x.dataState == 0);
            if (m == null) return ResultApi.error<tPowerStationDevice>(null, "数据丢失");
            if (!(await this._db.tUserPowerStation.AnyAsync(x => x.ups_powerStation_powerStationId_fk == m.devicePowerStation_powerStationId_fk && x.ups_user_userId_fk == this.userId)))
            {
                return ResultApi.error<tPowerStationDevice>(null, "无法操作此电站数据");
            }
            return ResultApi.ok<tPowerStationDevice>(m);
        }



        /// <summary>
        /// 新增设备
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultApi<decimal>> Create(tPowerStationDevice model)
        {
            //throw new Exception("停用功能");
            if (model.deviceType_keyId_fk == 820004 && !model.deviceDes.Contains(".m3u8"))
            {
                return ResultApi.error<decimal>(0, "当前系统只支持m3u8格式的监控");
            }

            model.deviceId = 0;
            await this.IsCheckPowerStation(model.devicePowerStation_powerStationId_fk);
            if (await this._db.tPowerStationDevice.AnyAsync(x => x.deviceTopic == model.deviceTopic))
            {
                return ResultApi.error<decimal>(0, "硬件编号已存在");
            }
            await this._db.tPowerStationDevice.AddAsync(model);
            await this._db.SaveChangesAsync();
            return ResultApi.okOrError<decimal>(model.deviceId > 0, model.deviceId);
        }


        /// <summary>
        /// 修改
        /// </summary>
        [HttpPut]
        public async Task<ResultApi<bool>> Modify(tPowerStationDevice model)
        {
            if (!(await this._db.tUserPowerStation.AnyAsync(x => x.ups_powerStation_powerStationId_fk == model.devicePowerStation_powerStationId_fk && x.ups_user_userId_fk == this.userId)))
            {
                return ResultApi.error<bool>(false, "无法操作此电站数据");
            }
            if (await this._db.tPowerStationDevice.AnyAsync(x => x.deviceTopic == model.deviceTopic && x.deviceId != model.deviceId))
            {
                return ResultApi.error<bool>(false, "硬件编号已存在");
            }
            await this._db.tPowerStationDevice.Where(x => x.deviceId == model.deviceId).UpdateAsync(x => new tPowerStationDevice
            {
                deviceName = model.deviceName,
                deviceTopic = model.deviceTopic,
                deviceType_keyId_fk = model.deviceType_keyId_fk,
                deviceDes = model.deviceDes,
                dataOrderBy = model.dataOrderBy
            });
            await this._db.SaveChangesAsync();
            return ResultApi.okOrError<bool>(true, true);
        }


        /// <summary>
        /// 解绑与绑定设备
        /// </summary>
        /// <param name="deviceId">设备ID</param>
        /// <param name="state">0表示绑定,2表示解绑</param>
        [HttpPut]
        public async Task<ResultApi<bool>> DeviceBind(decimal deviceId, int state = 2)
        {
            if (state != 0 && state != 2) return ResultApi.error(false, "状态出错");
            var m = await this._db.tPowerStationDevice.FirstOrDefaultAsync(x => x.deviceId == deviceId && x.dataState != 1);
            if (m == null) return ResultApi.error(false, "设备不存在");
            await this._db.tPowerStationDevice.Where(x => x.deviceId == deviceId).UpdateAsync(x => new tPowerStationDevice
            {
                dataState = state,
            });

            //if (state == 2)
            //{
            //    var ok = await this.mqtt.Disconnect(m.deviceSN);
            //    if (ok)
            //        await this._db.SaveChangesAsync();
            //    return ResultApi.okOrError<bool>(ok, ok);
            //}
            //else {
            await this._db.SaveChangesAsync();
            return ResultApi.okOrError<bool>(true, true);
            //}

        }

        /// <summary>
        /// 获取机组列表
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<Dictionary<string, string>>> GeneratorList(decimal powerStationId)
        {
            try
            {
                //设备管理界面用
                if (powerStationId == 0)
                {
                    return ResultApi.ok(new Dictionary<string, string>() { { "unit1", "1#" }, { "unit2", "2#" }, { "unit3", "3#" } }, 3);
                }

                List<vPowerStationDeviceGroup> groupList = await this._db.vPowerStationDeviceGroup.Where(x => x.devicePowerStation_powerStationId_fk == powerStationId).OrderBy(x => x.deviceGroup).ToListAsync();
                Dictionary<string, string> group = new Dictionary<string, string>();
                foreach (var item in groupList)
                {
                    group.Add(item.deviceGroupname, item.deviceGroup);
                }
                return ResultApi.ok(group, group.Count);
            }
            catch (Exception ex)
            {
                this._log.LogError(ex, "获取机组列表");
                return ResultApi.error<Dictionary<string, string>>(new Dictionary<string, string>());
            }
        }

        /// <summary>
        /// 导出数据
        /// </summary>
        /// <param name="powerStationid">电站ID</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<FileStreamResult> Download(int powerStationid)
        {
            if (!(await this._db.tUserPowerStation.AnyAsync(x => x.ups_powerStation_powerStationId_fk == powerStationid && x.ups_user_userId_fk == this.userId)))
            {
                throw new Exception("无法操作此电站数据");
            }
            var m = await this._db.vPowerStationDevice.Where(x => x.devicePowerStation_powerStationId_fk == powerStationid).ToListAsync();
            var titles = await this._db.tExcelTitle.Where(x => x.excelType == 8).ToListAsync();
            if (titles.Count == 0) return new FileStreamResult(new MemoryStream(), new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
            Task<Stream> task = Task.Run(async () =>
            {
                return ExcelExport.export<vPowerStationDevice>(m, titles);
            });
            return new FileStreamResult(await task, new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
        }


        /// <summary>
        /// 获取电站主题列表
        /// </summary>
        /// <param name="powerStationId">电站ID</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<List<tPowerStationDevice>>> DeviceList(decimal powerStationId)
        {
            IQueryable<tPowerStationDevice> q = this._db.tPowerStationDevice.Where(x => x.devicePowerStation_powerStationId_fk == powerStationId && (x.deviceType_keyId_fk == 820002 || x.deviceType_keyId_fk == 820096));
            return ResultApi.ok<List<tPowerStationDevice>>(await q.ToListAsync(), 0);
        }

        /// <summary>
        /// 发送指令
        /// </summary>
        /// <param name="Topic">接收指令的主题</param>
        /// <param name="value">指令值</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultApi<bool>> SendCmd(string Topic, decimal value)
        {

            var m = await this._db.tPowerStationDevice.FirstOrDefaultAsync(x => x.deviceTopic == Topic && x.dataState == 0);
            if (m == null) return ResultApi.error(false, "指令主题不存在");
            await this.IsCheckPowerStation(m.devicePowerStation_powerStationId_fk);
            bool obj = m.deviceType_keyId_fk == 820002 ? (await this.mqtt.SendDataToDevice(Topic, System.Text.Json.JsonSerializer.Serialize(new { value = Convert.ToInt32(value) }))) : await this.mqtt.SendDataToDevice(Topic, System.Text.Json.JsonSerializer.Serialize(new { value = value }));
            if (obj)
            {
                return ResultApi.ok(true, "指令已发送");
            }
            else
            {
                return ResultApi.error<bool>(false, "指令发送失败");
            }
        }

        /// <summary>
        /// 获取当前硬件数据
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<Dictionary<string, Dictionary<string, decimal>>>> GetLastValue(long powerStationId)
        {

            try
            {
                var TopicLastValue = new Dictionary<string, Dictionary<string, decimal>>();
                string SN = this._db.tPowerStation.Where(x => x.powerStationId == powerStationId && x.dataState == 0).Select(x => x.powerStationNo).FirstOrDefault();
                if(string.IsNullOrEmpty(SN)) return ResultApi.error<Dictionary<string, Dictionary<string, decimal>>>(null,"不存在的电站");
                var keys = _redisUtil.Keys($"/{SN}/*");
                foreach (var key in keys)
                {
                    var v = await _redisUtil.GetStringKey<Dictionary<string,decimal>>(key);
                    TopicLastValue.Add(key, v);
                }
                return ResultApi.ok(TopicLastValue, 0);
            }
            catch (Exception ex)
            {
                this._log.LogError(ex, "获取当前硬件数据");
                return ResultApi.ok(new Dictionary<string, Dictionary<string, decimal>>(), 0);
            }
        }

    }
}
